﻿using Aribaccio;
using Aribaccio.Device;
using Aribaccio.Device.Modbus;
using Aribaccio.Logger;
using BDPAutodetect.Device;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BDPAutodetect.Simcore
{
    public class DeviceSimulatorModbus : DeviceSimulatorBase, IDeviceTrans<IDeviceData<IDevice<IDevicePara>>>
    {
        /// <summary>
        /// 接收设备数据委托事件
        /// </summary>
        protected Action<ModbusSlaveData<StructInputShort>, string> DealWithAction;
        /// <summary>
        /// 设备通讯辅助实例
        /// </summary>
        protected DeviceSerialModbus<IDevicePara>? DeviceItem { get; set; }
        /// <summary>
        /// 是否打开
        /// </summary>
        public override bool IsOpen => this.DeviceItem?.IsOpen ?? false;
        /// <summary>
        /// 设备地址端口
        /// </summary>
        public override string DeviceAddressPort => this.DeviceItem?.AddressPort ?? string.Empty;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="argName">名称</param>
        /// <param name="argDeviceType">设备类型</param>
        /// <param name="argDeviceModule">设备模组类型</param>
        /// <param name="argDevice">设备连接</param>
        protected DeviceSimulatorModbus(string argName, DeviceType argDeviceType, DeviceModule argDeviceModule, DeviceSerialModbus<IDevicePara> argDevice)
            : base(argName, argDeviceType, argDeviceModule)
        {
            this.DeviceItem = argDevice;
            this.DealWithAction += DeviceDataDealWith;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();
            if (this.DeviceItem != null)
            {
                this.DeviceItem.BindingDevice(this);
            }
        }

        /// <summary>
        /// 接收设备数据[接口实现]
        /// </summary>
        /// <param name="argDeviceData">设备数据</param>
        public Task DeviceDataArrive(IDeviceData<IDevice<IDevicePara>> argDeviceData)
        {
            return Task.Run(() =>
            {
                DeviceDataModbus<IDevice<IDevicePara>> deviceDataModbus = (DeviceDataModbus<IDevice<IDevicePara>>)argDeviceData;
                if (deviceDataModbus == null || deviceDataModbus.DataModbus == null) return;

                this.SendMessageIn(deviceDataModbus.DataHexString);
                this.DealWithAction.Invoke(deviceDataModbus.DataModbus, deviceDataModbus.DataHexString);
            });
        }

        /// <summary>
        /// 接收设备数据处理
        /// </summary>
        public void DeviceDataDealWith(ModbusSlaveData<StructInputShort> argModbusData, string argModbusDataHex)
        {
            var commandData = this.DeviceDataParse(argModbusData, argModbusDataHex);
            if (commandData == null) return;

            //通知UI当前数据
            this.OnActiveDeviceCommandData(commandData);
            //检查定义是否返回，并返回仿真数据
            this.DeviceDataResponseWrite(commandData);
        }

        /// <summary>
        /// 接收设备数据解析
        /// </summary>
        /// <returns></returns>
        protected virtual DeviceCommandData? DeviceDataParse(ModbusSlaveData<StructInputShort> argModbusData, string argModbusDataHex)
        {
            var commandData = this.GetActiveDeviceCommandData(argModbusData.ToStringHex());
            if (commandData == null) return default;

            commandData.RealResponseCommand = string.Empty;
            commandData.RealCommandContent = argModbusDataHex;
            commandData.RealCommandReceivedTime = DateTime.Now;
            return commandData;
        }

        /// <summary>
        /// 设备数据响应写回
        /// </summary>
        /// <param name="argCommandData"></param>
        protected void DeviceDataResponseWrite(DeviceCommandData argCommandData)
        {
            if (!argCommandData.ResponseStatus) return;
            var bytes = this.DeviceDataResponseParse(argCommandData);
            //发送到串口
            var sendResult = this.DeviceItem?.SendSerialPortData(bytes);
            //输出响应信息
            string strResponseCommand = string.Join(" ", Array.ConvertAll(bytes.ToArray(), x => x.ToString("X2")));
            argCommandData.RealResponseCommand = strResponseCommand;
            //发送数据到UI界面显示
            this.SendMessageOut(strResponseCommand);
        }

        /// <summary>
        /// 设备数据响应解析
        /// </summary>
        /// <param name="argCommandData"></param>
        protected virtual byte[] DeviceDataResponseParse(DeviceCommandData argCommandData)
        {
            List<byte> responseBytes = new List<byte>();
            //获取响应指令
            string[] responseCommands = argCommandData.ResponseCommand.Split(" ");
            foreach (var item in responseCommands)
            {
                responseBytes.Add(Convert.ToByte(item, 16));
            }
            return responseBytes.ToArray();
        }
    }
}
